﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using System.Configuration;
using System.Net.Mail;
using System.Net;
using System.Text.RegularExpressions;
using System.IO;
//using WiSMsg.WeSMsg;

namespace WiSMsg
{
    public partial class WiSMsg : ServiceBase
    {
        [DllImport("kernel32.dll")]
        static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName);

        [DllImport("Kernel32.dll", SetLastError = true)]
        static extern IntPtr OpenEvent(uint dwDesiredAccess, bool bInheritHandle, string lpName);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);

        const uint STANDARD_RIGHTS_REQUIRED = 0x000F0000;
        const uint SYNCHRONIZE = 0x00100000;
        const uint EVENT_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3);
        const UInt32 INFINITE = 0xFFFFFFFF;

        IntPtr hdlCreate, hdlOpen;

        bool isWiSMsgThreadRunning = true;

        public WiSMsg()
        {
            InitializeComponent();
            loadSetting();
        }

        private void loadSetting()
        {
            if (!System.Diagnostics.EventLog.SourceExists("WiSTest_Source"))
            {
                System.Diagnostics.EventLog.CreateEventSource(
                   "WiSMsg_Source", "WiSMsg_Log");
            }
            evlWiSMsg.Source = "WiSMsg_Source";
            evlWiSMsg.Log = "WiSMsg_Log";
        }

        protected override void OnStart(string[] args)
        {
            try
            {
                logToSystem("On Start " + DateTime.Now.ToString(), EventLogEntryType.Information);
                hdlCreate = CreateEvent(IntPtr.Zero, false, false, "Global\\WiSMsg");

                if (hdlCreate != IntPtr.Zero)
                {
                    logToSystem("Handle created successfully. Value: " + hdlCreate.ToString(), EventLogEntryType.Information);
                    hdlOpen = OpenEvent(EVENT_ALL_ACCESS, false, "Global\\WiSMsg");
                    if (hdlOpen != IntPtr.Zero)
                    {
                        logToSystem("Handle openned successfully. Value: " + hdlOpen.ToString(), EventLogEntryType.Information);

                        Thread thread = new Thread(processWiSMsgDequeue);
                        thread.Start();

                    }
                }
                else
                {
                    logToSystem("Failed created. Value: " + hdlCreate.ToString(), EventLogEntryType.Error);
                }

            }
            catch (Exception ex)
            {
            }
        }
        public bool sendEmail(WeSMsg.Email email)
        {
            MailMessage message;
            SmtpClient smtp;
            try
            {
                string host = ConfigurationManager.AppSettings["host"];
                string from = ConfigurationManager.AppSettings["from"];
                string username = ConfigurationManager.AppSettings["username"];
                string password = ConfigurationManager.AppSettings["password"];
                int port = Convert.ToInt32(ConfigurationManager.AppSettings["port"]);
                
                message = new MailMessage();
                message.Bcc.Add(email.emailTo);

                message.Subject = email.subject;
                message.From = new MailAddress(from);
                message.Body = email.body;
                if (email.isHTMLEncoded == true)
                {
                    message.IsBodyHtml = true;
                }
                else
                    message.IsBodyHtml = false;
               /////////////////////////////////////////////////////////
                if (email.fileName != null || email.fileName != "")
                {
                    string path = ConfigurationManager.AppSettings["filepath"];
                    string file = email.fileName.Trim();
                    string[] result = Regex.Split(file, ",");

                    foreach (string sub in result)
                    {
                        string t = sub.Trim();
                        if (t != "")
                        {
                            string item = path + t;
                            if (File.Exists(item))
                            {
                                Attachment data = new Attachment(item);
                                message.Attachments.Add(data);
                            }
                        }
                    }
                }
                // set smtp details
                smtp = new SmtpClient(host);
                smtp.Port = port;
                smtp.EnableSsl = true;
                smtp.Credentials = new NetworkCredential(username, password);
                smtp.SendCompleted += new SendCompletedEventHandler(smtp_SendCompleted);
                string userState = email.id.ToString();
                smtp.SendAsync(message, userState); 
                return true;
            }
            catch (Exception ex)
            {
                using (WeSMsg.WeSMsgClient client = new WeSMsg.WeSMsgClient())
                {
                    client.downflag(email.id);
                }
                logToSystem("Email ID = [" + email.id.ToString() + "] EX= "+ex.ToString()+ "! " + DateTime.Now.ToString(), EventLogEntryType.Information);
            }
            return false;
        }
        void smtp_SendCompleted(object sender, AsyncCompletedEventArgs e)
        {
            String token = (string)e.UserState;
            if (e.Cancelled == true)
            {
                
                logToSystem("Email ID = ["+ token +"] sending cancelled! " + DateTime.Now.ToString(), EventLogEntryType.Information);
                
            }
            else if (e.Error != null)
            {
                using (WeSMsg.WeSMsgClient client = new WeSMsg.WeSMsgClient())
                {
                    client.downflag(Convert.ToInt32(token));
                }
                logToSystem("Email ID [" + token + "] sending error with message= " + e.Error.Message + DateTime.Now.ToString(), EventLogEntryType.Information);
            }
            else
            {
                logToSystem("Email ID [" + token+ "] sent sucessfully! " + DateTime.Now.ToString(), EventLogEntryType.Information);
            }

        }
        public void processWiSMsgDequeue()
        {
           
            try
            {
                using (WeSMsg.WeSMsgClient client = new WeSMsg.WeSMsgClient())
                {
                    logToSystem("WiSMsg Thread start dequeue " + DateTime.Now.ToString(), EventLogEntryType.Information);
                    while (isWiSMsgThreadRunning)
                    {
                        WeSMsg.WeSMsgDequeueResult dequeue = new WeSMsg.WeSMsgDequeueResult();
                        //WeSMsg.Email email = null;

                        dequeue = client.dequeue();
                        while (dequeue.msgResultStatus.statusCode == 0)
                        {
                            //string id = dequeue.email.id.ToString();
                            //logToSystem("Email ID = " + id + " is prepare to send! " + DateTime.Now.ToString(), EventLogEntryType.Information);
                            sendEmail(dequeue.email);
                            dequeue = client.dequeue();
                        }

                        logToSystem("WiSMsg Thread waiting for enqueue " + DateTime.Now.ToString(), EventLogEntryType.Information);
                        WaitForSingleObject(hdlOpen, INFINITE);
                        logToSystem("WiSMsg Thread resume working on " + DateTime.Now.ToString(), EventLogEntryType.Information);

                    }
                }
            }
            catch (Exception ex)
            {

            }
        }
        private void logToSystem(string msg, EventLogEntryType eventLogEntryType)
        {

            evlWiSMsg.WriteEntry(msg, eventLogEntryType);
        }

        protected override void OnStop()
        {
            try
            {
                logToSystem("On stop " + DateTime.Now.ToString(), EventLogEntryType.Information);
                isWiSMsgThreadRunning = false;
            }
            catch (Exception ex)
            {
            }
        }
    }
}
